通过层序和中序遍历序列重建二叉树
在学二叉树的重建时,在《算法笔记》上学到了如何通过先序(或后序)遍历序列和中序遍历序列重建二叉树,它也提出了一个问题:如何通过层序和中序遍历序列重建二叉树?我一开始按照先序和中序重建的思路思考,发现做不到。我无法确定一个点后面的点属于它的左子树还是右子树或者兄弟节点。于是我在网上查找,发现这方面的话题不多,其中还有一些不是用C++实现的。不过幸好还是找到了。于是在学习之后在这把它记录下来。
1 #include <cstdio> 2 3 const int INF = 0x3fffffff; 4 const int maxn = 10010; 5 6 struct Node 7 { 8 int x; 9 Node *left, *right; 10 }; 11 12 Node* root; 13 int levelorder[maxn], inorder[maxn]; 14 int n; 15 bool hashtable[maxn]; //标记levelorder中某个点是否被加入了树中 16 //如果没有hashtable, 当树中存在两个值相等的点时 , 17 Node* init() //可能导致在层序遍历中相同值的两个点前面的点被遍历两次,后面的点 18 { //没有被遍历,从而建树错误 19 Node* node = new Node; 20 node->x = 0; 21 node->left = NULL; 22 node->right = NULL; 23 return node; 24 } 25 26 Node* buildtree(int il, int ir, int ll, int lr) //当我给你一个二叉树的中序遍历时 27 { //这个中序遍历遍历一定有一个根节点 28 if(il == ir) //体现在层序遍历上时它一定先出现 29 { //所以顺序遍历层序遍历,一定可以先发现二叉树的根节点 30 Node* node = new Node; 31 node->x = inorder[il]; 32 hashtable[il] = true; 33 return node; 34 } 35 Node* node = new Node; 36 int i, j; 37 for(j = ll; j <= lr; j++) 38 { 39 bool flag = false; 40 for(i = il; i <= ir; i++) 41 { 42 if(inorder[i] == levelorder[j]&&hashtable[i] == false) 43 { 44 flag = true; 45 break; 46 } 47 } 48 if(flag) break; 49 } 50 node->left = buildtree(il, i-1, j+1, lr); 51 node->right = buildtree(i+1, ir, j+1, lr); 52 node->x = inorder[i]; 53 hashtable[i] = true; 54 return node; 55 } 56 57 int main() 58 { 59 scanf("%d", &n); 60 for(int i = 0; i < n; i++) scanf("%d", &inorder[i]); 61 for(int i = 0; i < n; i++) scanf("%d", &levelorder[i]); 62 root = buildtree(0, n-1, 0, n-1); 63 printf("%d\n", root->left->right->x); 64 return 0; 65 }
这个重建的方法利用了层序遍历序列中父子节点有先后顺序的特点。